package per.wei.diary.utils;

import java.util.Calendar;
import per.wei.diary.entity.MyDate;

public class MyCalendar {

	private final static MyDate BASE_DATE_TIME = new MyDate();

	private final static int[] DAYS_OF_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, };

	static {
		BASE_DATE_TIME.setYear(1970);
		BASE_DATE_TIME.setMonth(Calendar.JANUARY);
		BASE_DATE_TIME.setDay(1);
		BASE_DATE_TIME.setDayOfWeek(3);
	}
	
	private MyCalendar() {

	}

	private static boolean isYearValid(int year) {
		if (year < BASE_DATE_TIME.getYear()) {
			return false;
		}
		return true;
	}

	/**
	 * @param month 0~11
	 * @return
	 */
	private static boolean isMonthValid(int month) {
		if (month > Calendar.DECEMBER || month < Calendar.JANUARY) {
			return false;
		}
		return true;
	}

	public static int getDaysOfYearByYear(int year) {
		if (!isYearValid(year)) {
			return -1;
		}

		boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
		return isLeapYear ? 366 : 365;
	}

	public static int getDaysOfMonthByYearMonth(int year, int month) {
		if (!isYearValid(year)) {
			return -1;
		}

		if (!isMonthValid(month)) {
			return -1;
		}

		if (month == Calendar.FEBRUARY) {
			boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
			return isLeapYear ? 29 : 28;
		} else {
			return DAYS_OF_MONTH[month];
		}
	}

	public static int[][] getCalendarByYearMonth(int year, int month) {
		if (!isYearValid(year)) {
			return null;
		}

		if (!isMonthValid(month)) {
			return null;
		}

		int yearInterval = year - BASE_DATE_TIME.getYear();
		int monthInterval = month - BASE_DATE_TIME.getMonth();

		int dayInterval = 0;

		// To be optimized
		for (int i = 0; i < yearInterval; i++) {
			dayInterval += getDaysOfYearByYear(BASE_DATE_TIME.getYear() + i);
		}

		for (int i = 0; i < monthInterval; i++) {
			dayInterval += getDaysOfMonthByYearMonth(year, Calendar.JANUARY + i);
		}

		int firstDayOfMonthInWeek = (BASE_DATE_TIME.getDayOfWeek() + dayInterval) % 7;
		int daysOfThisMonth = getDaysOfMonthByYearMonth(year, month);

		int calendarArray[][] = new int[7][6];
		int loopDayOfMonth = 1;
		boolean loopStartFlag = false;
		for (int j = 0; j < 6; j++) {
			for (int i = 0; i < 7; i++) {
				if (loopStartFlag == false) {
					calendarArray[i][j] = 0;
					if (j == 0 && i == firstDayOfMonthInWeek) {
						loopStartFlag = true;
						calendarArray[i][j] = loopDayOfMonth++;
					}
				} else {
					calendarArray[i][j] = loopDayOfMonth;
					if (loopDayOfMonth > daysOfThisMonth) {
						loopStartFlag = false;
						calendarArray[i][j] = 0;
					}
					loopDayOfMonth++;
				}
			}
		}
		return calendarArray;
	}

	public static void printCalendar(int[][] calendarArray) {
		for (int j = 0; j < 6; j++) {
			for (int i = 0; i < 7; i++) {
				System.out.print(calendarArray[i][j] + "\t");
			}
			System.out.println();
		}
	}
}
